/*****************************************************************************************
   
   Copyright (c) Microsoft Corporation. All rights reserved.

   Use of this code sample is subject to the terms of the Microsoft
   Permissive License, a copy of which should always be distributed with
   this file.  You can also access a copy of this license agreement at:
   http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx

 ****************************************************************************************/

using System;

namespace GrooveWebServicesV12Helpers.Forms2
{
    /// <summary>
    /// Represents a Groove Forms tool.
    /// </summary>
    public class FormsTool :
        GrooveWebServicesV12Helpers.Tool,
        GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback
    {
        private GrooveForms2WebService.GrooveForms2 m_GrooveForms;

        internal static System.Collections.SortedList s_FormsToolEventManagerSortedList = new System.Collections.SortedList();
        private int m_FormsToolEventManagerCount = 0;

        private string m_FormsSubscriptionID;

        public FormsTool(GrooveWebServicesV12Helpers.Space i_Space, GrooveToolsWebService.Tool i_Tool)
            : this(i_Space, i_Tool, false)
        {
            //  Make sure we are dealing with a 12.0 or later Forms tool
            if (this.Type != GrooveWebServicesV12Helpers.Shared.GROOVE_FORMS2_TOOL_SUPPORTED_TYPE)
                throw new System.ArgumentException("Invalid tool type: " + this.Type);
        }

        protected FormsTool(GrooveWebServicesV12Helpers.Space i_Space, GrooveToolsWebService.Tool i_Tool, bool i_Derived)
            : base(i_Space, i_Tool)
        {
        }

        #region Forms Properties And Methods

        public static GrooveForms2WebService.GrooveForms2 CreateInitializedFormsWebService(string i_IdentityURL, string i_TargetURI, GrooveWebServicesV12Helpers.Context i_Context)
        {
            //  Create the service
            GrooveForms2WebService.GrooveForms2 FormsWebService = new GrooveForms2WebService.GrooveForms2();

            //  Create the Groove SOAP header
            FormsWebService.GrooveRequestHeaderValue = new GrooveForms2WebService.GrooveRequestHeader();

            //  Set appropriate header values
            FormsWebService.GrooveRequestHeaderValue.GrooveRequestKey = i_Context.RequestKey;
            FormsWebService.GrooveRequestHeaderValue.GrooveIdentityURL = i_IdentityURL;

            //  Set the URL
            FormsWebService.Url = i_Context.Host + i_TargetURI;

            //  Set Timeout
            FormsWebService.Timeout = i_Context.Timeout;

            return FormsWebService;
        }

        /// <summary>
        /// Array of Forms defined in the FormsTool.
        /// </summary>
        public GrooveWebServicesV12Helpers.Forms2.Form[] Forms
        {
            get
            {
                System.Collections.ArrayList FormsArrayList = new System.Collections.ArrayList();

                //  Get initialized reference to web service
                GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

                System.DateTime BeginDateTime = System.DateTime.Now;

                //  Ask service to provide the list of Forms entries for this tool
                GrooveForms2WebService.Form[] Forms = FormsWebService.ReadForms();

                if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
                {
                    System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                    System.Diagnostics.Debug.WriteLine("Forms2WebService::ReadForms, " + TimeSpan.TotalMilliseconds + " ms");
                }

                //  Create array list of Forms
                foreach (GrooveForms2WebService.Form Form in Forms)
                {
                    GrooveWebServicesV12Helpers.Forms2.Form NewForm = new GrooveWebServicesV12Helpers.Forms2.Form
                        (
                        this,
                        Form
                        );

                    FormsArrayList.Add(NewForm);
                }

                //  Return array from array list
                return (GrooveWebServicesV12Helpers.Forms2.Form[])FormsArrayList.ToArray(typeof(GrooveWebServicesV12Helpers.Forms2.Form));
            }
        }

        /// <summary>
        /// Mark records as "read".
        /// </summary>
        /// <param name="i_RecordURIs">Array of URIs for the records to be marked "read".</param>
        public void MarkRecordsRead(string[] i_RecordURIs)
        {
            this.SetUnreadStatus
                (
                i_RecordURIs,
                false			//  Unread
                );
        }

        /// <summary>
        /// Mark records as "unread".
        /// </summary>
        /// <param name="i_RecordURIs">Array of URIs for the records to be marked "unread".</param>
        public void MarkRecordsUnread(string[] i_RecordURIs)
        {
            this.SetUnreadStatus
                (
                i_RecordURIs,
                true			//  Unread
                );
        }

        /// <summary>
        /// A RecordDataSet containing the schema of the tool.
        /// </summary>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet Schema
        {
            get
            {
                return int_QueryRecords
                    (
                    "",									//  FormURI
                    false,								//  IncludeFileAttachmentContent,
                    true,								//  QueryMetaDataOnly
                    false,								//  UnreadRecordsOnly
                    "",									//  ViewURI
                    ""									//  WhereClause
                    );
            }
        }

        /// <summary>
        /// A RecordDataSet containing all data records in the tool.
        /// </summary>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet Records
        {
            get
            {
                return int_QueryRecords
                    (
                    "",									//  FormURI
                    false,								//  IncludeFileAttachmentContent,
                    false,								//  QueryMetaDataOnly
                    false,								//  UnreadRecordsOnly
                    "",									//  ViewURI
                    ""									//  WhereClause
                    );
            }
        }

        /// <summary>
        /// Get data records in the tool.
        /// </summary>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetRecords(bool i_IncludeFileAttachmentContent)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                "",									//  ViewURI
                ""									//  WhereClause
                );
        }

        /// <summary>
        /// Get data records in the tool.
        /// </summary>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <param name="i_UnreadRecordsOnly">true to include only "unread" records.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetRecords(bool i_IncludeFileAttachmentContent, bool i_UnreadRecordsOnly)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                i_UnreadRecordsOnly,
                "",									//  ViewURI
                ""									//  WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool.
        /// </summary>
        /// <param name="i_WhereClause">Specifies the condition to select records. The syntax of the clause is similar to an SQL where clause; refer to Groove documentation for details.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet QueryRecords(string i_WhereClause)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                false,								//  IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                "",									//  ViewURI
                i_WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool.
        /// </summary>
        /// <param name="i_WhereClause">Specifies the condition to select records. The syntax of the clause is similar to an SQL where clause; refer to Groove documentation for details.</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet QueryRecords(string i_WhereClause, bool i_IncludeFileAttachmentContent)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                "",									//  ViewURI
                i_WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool.
        /// </summary>
        /// <param name="i_WhereClause">Specifies the condition to select records. The syntax of the clause is similar to an SQL where clause; refer to Groove documentation for details.</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <param name="i_UnreadRecordsOnly">true to include only "unread" records.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet QueryRecords(string i_WhereClause, bool i_IncludeFileAttachmentContent, bool i_UnreadRecordsOnly)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                i_UnreadRecordsOnly,
                "",									//  ViewURI
                i_WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which use a particular form.
        /// </summary>
        /// <param name="i_FormURI">URI of the form</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetFormRecords(string i_FormURI)
        {
            return int_QueryRecords
                (
                i_FormURI,
                false,								//  IncludeFileAttachmentContent
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                "",									//  ViewURI
                ""									//  WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which use a particular form.
        /// </summary>
        /// <param name="i_FormURI">URI of the form</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetFormRecords(string i_FormURI, bool i_IncludeFileAttachmentContent)
        {
            return int_QueryRecords
                (
                i_FormURI,
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                "",									//  ViewURI
                ""									//  WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which use a particular form.
        /// </summary>
        /// <param name="i_FormURI">URI of the form</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <param name="i_UnreadRecordsOnly">true to include only "unread" records.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetFormRecords(string i_FormURI, bool i_IncludeFileAttachmentContent, bool i_UnreadRecordsOnly)
        {
            return int_QueryRecords
                (
                i_FormURI,
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                i_UnreadRecordsOnly,
                "",									//  ViewURI
                ""									//  WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which use a particular form.
        /// </summary>
        /// <param name="i_FormURI">URI of the form</param>
        /// <param name="i_WhereClause">Specifies the condition to select records. The syntax of the clause is similar to an SQL where clause; refer to Groove documentation for details.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet QueryFormRecords(string i_FormURI, string i_WhereClause)
        {
            return int_QueryRecords
                (
                i_FormURI,
                false,								//  IncludeFileAttachmentContent
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                "",									//  ViewURI
                i_WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which use a particular form.
        /// </summary>
        /// <param name="i_FormURI">URI of the form</param>
        /// <param name="i_WhereClause">Specifies the condition to select records. The syntax of the clause is similar to an SQL where clause; refer to Groove documentation for details.</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet QueryFormRecords(string i_FormURI, string i_WhereClause, bool i_IncludeFileAttachmentContent)
        {
            return int_QueryRecords
                (
                i_FormURI,
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                "",									//  ViewURI
                i_WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which use a particular form.
        /// </summary>
        /// <param name="i_FormURI">URI of the form</param>
        /// <param name="i_WhereClause">Specifies the condition to select records. The syntax of the clause is similar to an SQL where clause; refer to Groove documentation for details.</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <param name="i_UnreadRecordsOnly">true to include only "unread" records.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet QueryFormRecords(string i_FormURI, string i_WhereClause, bool i_IncludeFileAttachmentContent, bool i_UnreadRecordsOnly)
        {
            return int_QueryRecords
                (
                i_FormURI,
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                i_UnreadRecordsOnly,
                "",									//  ViewURI
                i_WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which appear in a particular view.
        /// </summary>
        /// <param name="i_ViewURI">URI of the view</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetViewRecords(string i_ViewURI)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                false,								//  IncludeFileAttachmentContent
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                i_ViewURI,
                ""									//  WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which appear in a particular view.
        /// </summary>
        /// <param name="i_ViewURI">URI of the view</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetViewRecords(string i_ViewURI, bool i_IncludeFileAttachmentContent)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                i_ViewURI,
                ""									//  WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which appear in a particular view.
        /// </summary>
        /// <param name="i_ViewURI">URI of the view</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <param name="i_UnreadRecordsOnly">true to include only "unread" records.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetViewRecords(string i_ViewURI, bool i_IncludeFileAttachmentContent, bool i_UnreadRecordsOnly)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                i_UnreadRecordsOnly,
                i_ViewURI,
                ""									//  WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which appear in a particular view.
        /// </summary>
        /// <param name="i_ViewURI">URI of the view</param>
        /// <param name="i_WhereClause">Specifies the condition to select records. The syntax of the clause is similar to an SQL where clause; refer to Groove documentation for details.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet QueryViewRecords(string i_ViewURI, string i_WhereClause)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                false,								//  IncludeFileAttachmentContent
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                i_ViewURI,
                i_WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which appear in a particular view.
        /// </summary>
        /// <param name="i_ViewURI">URI of the view</param>
        /// <param name="i_WhereClause">Specifies the condition to select records. The syntax of the clause is similar to an SQL where clause; refer to Groove documentation for details.</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet QueryViewRecords(string i_ViewURI, string i_WhereClause, bool i_IncludeFileAttachmentContent)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                false,								//  UnreadRecordsOnly
                i_ViewURI,
                i_WhereClause
                );
        }

        /// <summary>
        /// Query for records in the tool which appear in a particular view.
        /// </summary>
        /// <param name="i_ViewURI">URI of the view</param>
        /// <param name="i_WhereClause">Specifies the condition to select records. The syntax of the clause is similar to an SQL where clause; refer to Groove documentation for details.</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <param name="i_UnreadRecordsOnly">true to include only "unread" records.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet QueryViewRecords(string i_ViewURI, string i_WhereClause, bool i_IncludeFileAttachmentContent, bool i_UnreadRecordsOnly)
        {
            return int_QueryRecords
                (
                "",									//  FormURI
                i_IncludeFileAttachmentContent,
                false,								//  QueryMetaDataOnly
                i_UnreadRecordsOnly,
                i_ViewURI,
                i_WhereClause
                );
        }

        internal GrooveWebServicesV12Helpers.Forms2.RecordDataSet int_QueryRecords(string i_FormURI, bool i_IncludeFileAttachmentContent, bool i_QueryMetaDataOnly, bool i_UnreadRecordsOnly, string i_ViewURI, string i_WhereClause)
        {
            GrooveWebServicesV12Helpers.Forms2.RecordDataSet NewRecordDataSet;

            //  Get initialized reference to web service
            GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

            //  Ask service to provide the list of all records
            GrooveForms2WebService.RecordQuery RecordQuery = new GrooveForms2WebService.RecordQuery();
            RecordQuery.FormURI = i_FormURI;
            RecordQuery.IncludeFileAttachmentContent = i_IncludeFileAttachmentContent;
            RecordQuery.QueryMetadataOnly = i_QueryMetaDataOnly;
            RecordQuery.UnreadRecordsOnly = i_UnreadRecordsOnly;
            RecordQuery.ViewURI = i_ViewURI;
            RecordQuery.WhereClause = i_WhereClause;

            System.DateTime BeginDateTime = System.DateTime.Now;

            //  Ask service to query records
            GrooveForms2WebService.Forms2RecordDataSet FormsRecordDataSet = FormsWebService.QueryRecords(RecordQuery);

            if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
            {
                System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                System.Diagnostics.Debug.WriteLine("Forms2WebService::QueryRecords, " + TimeSpan.TotalMilliseconds + " ms");
            }

            NewRecordDataSet = new GrooveWebServicesV12Helpers.Forms2.RecordDataSet(FormsRecordDataSet);
            return NewRecordDataSet;
        }

        /// <summary>
        /// Retrieve a set of records.
        /// </summary>
        /// <param name="i_RecordURIs">Array of record URIs to retrieve.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetRecords(string[] i_RecordURIs)
        {
            return int_GetRecords
                (
                i_RecordURIs,
                false, 
                false
                );
        }

        /// <summary>
        /// Retrieve a set of records.
        /// </summary>
        /// <param name="i_RecordURIs">Array of record URIs to retrieve.</param>
        /// <param name="i_IncludeFileAttachmentContent">true to include file attachment content.</param>
        /// <returns>RecordDataSet</returns>
        public GrooveWebServicesV12Helpers.Forms2.RecordDataSet GetRecords(string[] i_RecordURIs, bool i_IncludeFileAttachmentContent)
        {
            return int_GetRecords
                (
                i_RecordURIs,
                i_IncludeFileAttachmentContent,
                false
                );
        }

        internal GrooveWebServicesV12Helpers.Forms2.RecordDataSet int_GetRecords(string[] i_RecordURIs, bool i_IncludeFileAttachmentContent, bool i_ExceptionIfDeleted)
        {
            GrooveWebServicesV12Helpers.Forms2.RecordDataSet NewRecordDataSet;

            //  Get initialized reference to web service
            GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

            System.DateTime BeginDateTime = System.DateTime.Now;

            //  Ask service to provide the list of Forms entries for this tool
            GrooveForms2WebService.Forms2RecordDataSet FormsRecordDataSet = FormsWebService.ReadRecords
                (
                i_RecordURIs,
                i_IncludeFileAttachmentContent,
                i_ExceptionIfDeleted
                );

            if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
            {
                System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                System.Diagnostics.Debug.WriteLine("Forms2WebService::ReadRecords, " + TimeSpan.TotalMilliseconds + " ms");
            }

            NewRecordDataSet = new GrooveWebServicesV12Helpers.Forms2.RecordDataSet(FormsRecordDataSet);
            return NewRecordDataSet;
        }

        /// <summary>
        /// Retrieve the tool's ToolProperties.
        /// </summary>
        public GrooveWebServicesV12Helpers.Forms2.ToolProperties ToolProperties
        {
            get
            {
                GrooveWebServicesV12Helpers.Forms2.ToolProperties NewToolProperties;

                //  Get initialized reference to web service
                GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

                System.DateTime BeginDateTime = System.DateTime.Now;

                //  Ask service to provide tool properties
                GrooveForms2WebService.ToolProperties ToolProperties = FormsWebService.ReadToolProperties();

                if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
                {
                    System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                    System.Diagnostics.Debug.WriteLine("Forms2WebService::ReadToolProperties, " + TimeSpan.TotalMilliseconds + " ms");
                }

                NewToolProperties = new GrooveWebServicesV12Helpers.Forms2.ToolProperties(this, ToolProperties);
                return NewToolProperties;
            }
        }

        /// <summary>
        /// Array of Views defined in the FormsTool.
        /// </summary>
        public GrooveWebServicesV12Helpers.Forms2.View[] Views
        {
            get
            {
                System.Collections.ArrayList ViewsArrayList = new System.Collections.ArrayList();

                //  Get initialized reference to web service
                GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

                System.DateTime BeginDateTime = System.DateTime.Now;

                //  Ask service to provide the list of View entries for this tool
                GrooveForms2WebService.FormsView[] Views = FormsWebService.ReadViews();

                if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
                {
                    System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                    System.Diagnostics.Debug.WriteLine("Forms2WebService::ReadViews, " + TimeSpan.TotalMilliseconds + " ms");
                }

                //  Create array list of Views
                foreach (GrooveForms2WebService.FormsView View in Views)
                {
                    GrooveWebServicesV12Helpers.Forms2.View NewView = new GrooveWebServicesV12Helpers.Forms2.View
                        (
                        this,
                        View
                        );

                    ViewsArrayList.Add(NewView);
                }

                //  Return array from array list
                return (GrooveWebServicesV12Helpers.Forms2.View[])ViewsArrayList.ToArray(typeof(GrooveWebServicesV12Helpers.Forms2.View));
            }
        }

        /// <summary>
        /// True if this forms tool is designed.
        /// </summary>
        public bool DesignInitialized
        {
            get
            {
                //  Get initialized reference to web service
                GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

                System.DateTime BeginDateTime = System.DateTime.Now;

                //  Ask service to get design initialization state
                bool IsFormsToolDesignInitialized = FormsWebService.IsFormsToolDesignInitialized();

                if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
                {
                    System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                    System.Diagnostics.Debug.WriteLine("Forms2WebService::IsFormsToolDesignInitialized, " + TimeSpan.TotalMilliseconds + " ms");
                }

                return IsFormsToolDesignInitialized;
            }
        }

        /// <summary>
        /// Add records to the FormsTool.
        /// </summary>
        /// <param name="i_RecordDataSet">RecordDataSet containing records to be added.</param>
        /// <returns>Array of record URIs.</returns>
        public string[] AddRecords(GrooveWebServicesV12Helpers.Forms2.RecordDataSet i_RecordDataSet)
        {
            //  Get initialized reference to web service
            GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

            //  Set parameters
            GrooveForms2WebService.Forms2RecordDataSet FormsRecordDataSet = new GrooveForms2WebService.Forms2RecordDataSet();
            FormsRecordDataSet.Schema = i_RecordDataSet.Schema;
            FormsRecordDataSet.Data = i_RecordDataSet.Data;

            System.DateTime BeginDateTime = System.DateTime.Now;

            //  Ask service to create records
            string[] RecordURIs = FormsWebService.CreateRecords(FormsRecordDataSet);

            if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
            {
                System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                System.Diagnostics.Debug.WriteLine("Forms2WebService::CreateRecords, " + TimeSpan.TotalMilliseconds + " ms");
            }

            return RecordURIs;
        }

        /// <summary>
        /// Update records in the FormsTool.
        /// </summary>
        /// <param name="i_RecordDataSet">RecordDataSet containing records to be updated.</param>
        public void UpdateRecords(GrooveWebServicesV12Helpers.Forms2.RecordDataSet i_RecordDataSet)
        {
            //  Get initialized reference to web service
            GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

            //  Set parameters
            GrooveForms2WebService.Forms2RecordDataSet FormsRecordDataSet = new GrooveForms2WebService.Forms2RecordDataSet();
            FormsRecordDataSet.Schema = i_RecordDataSet.Schema;
            FormsRecordDataSet.Data = i_RecordDataSet.Data;

            System.DateTime BeginDateTime = System.DateTime.Now;

            //  Ask service to update records
            FormsWebService.UpdateRecords
                (
                FormsRecordDataSet,
                false					//  Exception if deleted
                );

            if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
            {
                System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                System.Diagnostics.Debug.WriteLine("Forms2WebService::UpdateRecords, " + TimeSpan.TotalMilliseconds + " ms");
            }
        }

        /// <summary>
        /// Delete records in the FormsTool.
        /// </summary>
        /// <param name="i_RecordURIs">Array of URIs for the records to be deleted.</param>
        public void RemoveRecords(string[] i_RecordURIs)
        {
            //  Get initialized reference to web service
            GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

            System.DateTime BeginDateTime = System.DateTime.Now;

            //  Ask service to delete records
            FormsWebService.DeleteRecords
                (
                i_RecordURIs,
                false			// Exception if deleted
                );

            if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
            {
                System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                System.Diagnostics.Debug.WriteLine("Forms2WebService::DeleteRecords, " + TimeSpan.TotalMilliseconds + " ms");
            }
        }

        /// <summary>
        /// Mark records as "read" or "unread".
        /// </summary>
        /// <param name="i_RecordURIs">Array of URIs for the records to be marked as "read" or "unread".</param>
        /// <param name="i_Unread">true to mark "unread", false to mark "read".</param>
        internal void SetUnreadStatus(string[] i_RecordURIs, bool i_Unread)
        {
            //  Get initialized reference to web service
            GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

            System.DateTime BeginDateTime = System.DateTime.Now;

            //  Ask service to update unread status
            FormsWebService.UpdateUnreadMark
                (
                i_Unread,
                i_RecordURIs,
                false			//  Exception if deleted
                );

            if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
            {
                System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                System.Diagnostics.Debug.WriteLine("Forms2WebService::UpdateUnreadMark, " + TimeSpan.TotalMilliseconds + " ms");
            }
        }

        /// <summary>
        /// Replaces the design of one or more target Forms tools with the design of this FormsTool.
        /// </summary>
        /// <param name="i_TargetFormsToolURIs">Array of target forms tool URIs.</param>
        /// <returns>Array of forms tool URIs which were updated.</returns>
        public void ReplaceDesign(string i_TargetFormsToolURI)
        {
            System.Collections.ArrayList UpdatedFormsToolURIs = new System.Collections.ArrayList();

            //  Get initialized reference to web service
            GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

            System.DateTime BeginDateTime = System.DateTime.Now;

            //  Ask service to replace design
            FormsWebService.ReplaceDesign(i_TargetFormsToolURI);

            if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
            {
                System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                System.Diagnostics.Debug.WriteLine("Forms2WebService::ReplaceDesign, " + TimeSpan.TotalMilliseconds + " ms");
            }
        }

        public GrooveForms2WebService.InfoPathTemplate ReadInfoPathTemplate(string i_FormURI)
        {
            //  Get initialized reference to web service
            GrooveForms2WebService.GrooveForms2 FormsWebService = this.GetInitializedFormsWebService(this.Data);

            System.DateTime BeginDateTime = System.DateTime.Now;

            //  Ask service to replace design
            GrooveForms2WebService.InfoPathTemplate InfoPathTemplate = FormsWebService.ReadInfoPathTemplate(i_FormURI);

            if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
            {
                System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                System.Diagnostics.Debug.WriteLine("Forms2WebService::ReadInfoPathTemplate, " + TimeSpan.TotalMilliseconds + " ms");
            }

            return InfoPathTemplate;
        }

        protected GrooveForms2WebService.GrooveForms2 GetInitializedFormsWebService(string i_TargetURI)
        {
            if ((m_GrooveForms == null) || Context.ReinitNeeded(m_GrooveForms.GrooveRequestHeaderValue.GrooveRequestKey))
            {
                m_GrooveForms = GrooveWebServicesV12Helpers.Forms2.FormsTool.CreateInitializedFormsWebService
                    (
                    m_IdentityURL,
                    i_TargetURI,
                    Context
                    );
            }
            else
            {
                //  Explicitly overwrite target URL and Timeout
                m_GrooveForms.Url = Context.Host + i_TargetURI;
                m_GrooveForms.Timeout = Context.Timeout;
            }

            return m_GrooveForms;
        }

        #endregion

        #region Forms Event Handling

        protected void IncrementFormsToolSubscriptionCount()
        {
            lock (s_FormsToolEventManagerSortedList)
            {
                if (m_FormsToolEventManagerCount == 0)
                {
                    m_FormsSubscriptionID = GrooveWebServicesV12Helpers.EventManager.AddEventListener
                        (
                        Context,
                        this.IdentityURL,
                        GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_FORMS2_EVENT_CLASS,
                        this.Data,
                        GrooveWebServicesV12Helpers.EventManager.s_EventURI,
                        this
                        );
                }

                ++m_FormsToolEventManagerCount;
            }
        }

        protected void DecrementFormsToolSubscriptionCount()
        {
            lock (s_FormsToolEventManagerSortedList)
            {
                --m_FormsToolEventManagerCount;

                if (m_FormsToolEventManagerCount == 0)
                {
                    GrooveWebServicesV12Helpers.EventManager.RemoveEventListener
                        (
                        m_FormsSubscriptionID,
                        this
                        );

                    m_FormsSubscriptionID = null;
                }
            }
        }

        public delegate void OnFormRecordsAddedDelegate(GrooveWebServicesV12Helpers.Forms2.RecordDataSet i_RecordDataSet);
        internal event OnFormRecordsAddedDelegate InternalOnFormRecordsAddedEvent;

        /// <summary>
        /// Event fired when records are added to the FormsTool
        /// </summary>
        public event OnFormRecordsAddedDelegate OnFormRecordsAddedEvent
        {
            add
            {
                IncrementFormsToolSubscriptionCount();
                InternalOnFormRecordsAddedEvent += value;
            }
            remove
            {
                InternalOnFormRecordsAddedEvent -= value;
                DecrementFormsToolSubscriptionCount();
            }
        }

        public delegate void OnFormRecordsRemovedDelegate(string[] i_RecordIDs);
        internal event OnFormRecordsRemovedDelegate InternalOnFormRecordsRemovedEvent;

        /// <summary>
        /// Event fired when records are deleted from the FormsTool
        /// </summary>
        public event OnFormRecordsRemovedDelegate OnFormRecordsRemovedEvent
        {
            add
            {
                IncrementFormsToolSubscriptionCount();
                InternalOnFormRecordsRemovedEvent += value;
            }
            remove
            {
                InternalOnFormRecordsRemovedEvent -= value;
                DecrementFormsToolSubscriptionCount();
            }
        }

        public delegate void OnFormRecordsUpdatedDelegate(GrooveWebServicesV12Helpers.Forms2.RecordDataSet i_RecordDataSet);
        internal event OnFormRecordsUpdatedDelegate InternalOnFormRecordsUpdatedEvent;

        /// <summary>
        /// Event fired when records are updated in the FormsTool
        /// </summary>
        public event OnFormRecordsUpdatedDelegate OnFormRecordsUpdatedEvent
        {
            add
            {
                IncrementFormsToolSubscriptionCount();
                InternalOnFormRecordsUpdatedEvent += value;
            }
            remove
            {
                InternalOnFormRecordsUpdatedEvent -= value;
                DecrementFormsToolSubscriptionCount();
            }
        }

        internal void RaiseFormRecordsAddedEvent(GrooveForms2WebService.Forms2RecordDataSet i_FormsRecordDataSet)
        {
            //  If one or more subscribers, broadcast event
            if (this.InternalOnFormRecordsAddedEvent != null)
            {
                GrooveWebServicesV12Helpers.Forms2.RecordDataSet RecordDataSet = new GrooveWebServicesV12Helpers.Forms2.RecordDataSet(i_FormsRecordDataSet);
                InternalOnFormRecordsAddedEvent(RecordDataSet);
            }
        }

        internal void RaiseFormRecordsRemovedEvent(string[] i_RecordIDs)
        {
            //  If one or more subscribers, broadcast event
            if (InternalOnFormRecordsRemovedEvent != null)
                InternalOnFormRecordsRemovedEvent(i_RecordIDs);
        }

        internal void RaiseFormRecordsUpdatedEvent(GrooveForms2WebService.Forms2RecordDataSet i_FormsRecordDataSet)
        {
            //  If one or more subscribers, broadcast event
            if (InternalOnFormRecordsUpdatedEvent != null)
            {
                GrooveWebServicesV12Helpers.Forms2.RecordDataSet RecordDataSet = new GrooveWebServicesV12Helpers.Forms2.RecordDataSet(i_FormsRecordDataSet);
                InternalOnFormRecordsUpdatedEvent(RecordDataSet);
            }
        }

        #endregion

        #region GrooveWebServicesV12HelpersBase Implementation

        public override object BindToObject(ref string[] i_URLParts, int i_URLPartIndex)
        {
            object BindResult = null;
            string RelativeURL = i_URLParts[i_URLPartIndex];
            string[] RelativeURLParts = RelativeURL.Split(new char[] { '#' });

            string ObjectType = RelativeURLParts[0];

            if (ObjectType == "Form")
            {
                string FormURI = this.URI + "/DataModelDelegate/FormID=" + RelativeURLParts[1];
                FormURI = FormURI.Replace("Tools/", "Forms2/");

                try
                {
                    //  ---------------------------------------------------------------------------------------
                    //  HACK ALERT:  Since there is no ReadForm method, must read all forms and do uri match

                    foreach (GrooveWebServicesV12Helpers.Forms2.Form Form in this.Forms)
                    {
                        if (Form.URI == FormURI)
                        {
                            BindResult = Form;
                            break;
                        }
                    }

                    //  ---------------------------------------------------------------------------------------
                }
                catch (System.Exception Exception)
                {
                    throw new System.Exception("Unable to find Form '" + FormURI + "' (" + Exception.Message + ")");
                }

                //  If there are more url parts, continue binding
                if (i_URLParts.Length > ++i_URLPartIndex)
                {
                    GrooveWebServicesV12Helpers.IBindServices IBindServices = (GrooveWebServicesV12Helpers.IBindServices)BindResult;
                    BindResult = IBindServices.BindToObject(ref i_URLParts, i_URLPartIndex);
                }
            }
            else if (ObjectType == "View")
            {
                string ViewURI = this.URI + "/DataModelDelegate/ViewID=" + RelativeURLParts[1];
                ViewURI = ViewURI.Replace("Tools/", "Forms2/");

                try
                {
                    //  ---------------------------------------------------------------------------------------
                    //  HACK ALERT:  Since there is no ReadView method, must read all views and do uri match

                    foreach (GrooveWebServicesV12Helpers.Forms2.View View in this.Views)
                    {
                        if (View.URI == ViewURI)
                        {
                            BindResult = View;
                            break;
                        }
                    }

                    //  ---------------------------------------------------------------------------------------
                }
                catch (System.Exception Exception)
                {
                    throw new System.Exception("Unable to find View '" + ViewURI + "' (" + Exception.Message + ")");
                }
            }
            else
                throw new System.Exception("Unknown forms tool url part - '" + ObjectType + "'");

            return BindResult;
        }

        #endregion


        #region IGrooveWebServicesEventCallback Members

        public void ProcessEvent(GrooveEventsWebService.Event i_Event)
        {
            switch (i_Event.EventType)
            {
                case GrooveWebServicesV12Helpers.Shared.GROOVE_FORMS2_RECORD_ADD_EVENT_TYPE:
                    {
                        GrooveEventsWebService.GrooveForms2RecordAddEventData FormsRecordAddEventData = (GrooveEventsWebService.GrooveForms2RecordAddEventData)i_Event.EventData;
                        this.RaiseFormRecordsAddedEvent(FormsRecordAddEventData.RecordDataSet);

                        break;
                    }

                case GrooveWebServicesV12Helpers.Shared.GROOVE_FORMS2_RECORD_DELETE_EVENT_TYPE:
                    {
                        GrooveEventsWebService.GrooveForms2RecordDeleteEventData FormsRecordDeleteEventData = (GrooveEventsWebService.GrooveForms2RecordDeleteEventData)i_Event.EventData;
                        this.RaiseFormRecordsRemovedEvent(FormsRecordDeleteEventData.RecordIDs);

                        break;
                    }

                case GrooveWebServicesV12Helpers.Shared.GROOVE_FORMS2_RECORD_UPDATE_EVENT_TYPE:
                    {
                        GrooveEventsWebService.GrooveForms2RecordUpdateEventData FormsRecordUpdateEventData = (GrooveEventsWebService.GrooveForms2RecordUpdateEventData)i_Event.EventData;
                        this.RaiseFormRecordsUpdatedEvent(FormsRecordUpdateEventData.RecordDataSet);

                        break;
                    }

                default:
                    {
                        System.Diagnostics.Debug.WriteLine("[Forms2Tool]Unknown event type: " + i_Event.EventType);
                        break;
                    }
            }
        }

        #endregion
    }
}
